package order

import (
	"context"
	"encoding/json"
	"fmt"
	"strings"
	"time"

	"sale-admin/config/redis"
	"sale-admin/internal/app/web/schema"
	"sale-admin/internal/app/web/service"
	"sale-admin/internal/app/web/service/common"
	"sale-admin/internal/app/web/service/coupon"
	"sale-admin/internal/app/web/service/pay"
	"sale-admin/internal/dal"
	"sale-admin/internal/dao"
	"sale-admin/internal/define"
	"sale-admin/internal/models"
	"sale-admin/internal/pkg"
	"sale-admin/internal/pkg/points"

	"192.168.1.75/go-pkg/errorx"
	"192.168.1.75/go-pkg/helper"
	"192.168.1.75/go-pkg/logx"
	"github.com/golang-module/carbon"
	"github.com/shopspring/decimal"
	"github.com/stripe/stripe-go/v74"
	"github.com/stripe/stripe-go/v74/refund"
	"gorm.io/gorm"
)

type OrderRefund struct{}

// CreateRefundOrder 创建退款订单
// paymentAmount 订单总金额
// refundAmount 退款金额
// endOutTradeNo 确认订单号！！！
// outRefundNo 退款订单号
func (or OrderRefund) CreateRefundOrder(db *gorm.DB, merchantID, RobotName, salesID string, paymentAmount, refundAmount float64,
	outTradeNo, endOutTradeNo, aliPayRes, wechatPayRes string, payStatus int8,
	reason, remarks, refundUserID string,
) (refundCode int) {
	var data models.MaOrderRefund
	data.ID = merchantID
	data.RobotName = RobotName
	data.SalesID = salesID
	data.PaymentAmount = paymentAmount      // 总的金额
	data.RefundPaymentAmount = refundAmount // 退款金额
	data.OutTradeNo = outTradeNo
	data.OutReFundNo = endOutTradeNo
	data.AliPayResult = aliPayRes
	data.WeChatResult = wechatPayRes
	data.Type = 1
	data.PayStatus = int(payStatus)
	data.Reason = reason // 0-网络异常订单支付未出货 1-货品出错 2-商品质量问题 3-其他
	data.Remarks = remarks
	data.RefundUserID = refundUserID
	data.AddTime = time.Now()
	count := db.Model(&models.MaOrderRefund{}).Create(&data).RowsAffected
	if count == 0 {
		return 0
	} else {
		return 1
	}
}

// 手动退款
func (or OrderRefund) Refund(ctx context.Context, db *gorm.DB,
	merchantID,
	outTradeNo string,
	paymentAmount float64,
	reason string,
	userID string,
) (
	data interface{},
	err error,
) {

	logx.Info(ctx, "Refund", logx.Any("outTradeNo", outTradeNo))
	logx.Info(ctx, "Refund", logx.Any("paymentAmount", fmt.Sprint(paymentAmount)))
	logx.Info(ctx, "Refund", logx.Any("reason", reason))
	logx.Info(ctx, "Refund", logx.Any("userID", userID))
	if outTradeNo == "" {
		err = errorx.New("交易号不能为空", -1)
		return
	}
	logx.Info(ctx, "order_trace:"+outTradeNo, logx.Any("type", "manual refund order"))
	if reason == "" {
		err = errorx.New("退款原因不能为空", -1)
		return
	}
	remarks := reason

	var orderCount int64
	var orderInfo schema.MyOrderInfo
	// 多订单相同时，需要sum总金额
	db.Model(&models.MaOrder{}).
		Where("out_trade_no = ? ", outTradeNo). // 单个商品传主订，多个传子单
		Select("*, sum(payment_amount) as total_payment_amount").
		Take(&orderInfo).
		Count(&orderCount) // sum原因使用count

	logx.Info(ctx, "Refund", logx.Any("orderCount", fmt.Sprint(orderCount)))
	if orderCount == 0 {
		orderCount = db.Model(&models.MaOrder{}).
			Where("child_out_trade_no = ?", outTradeNo). // 单个商品传主订，多个传子单
			Select("*, sum(payment_amount) as total_payment_amount").
			Take(&orderInfo).
			RowsAffected
		if orderCount == 0 {
			err = errorx.New("找不到订单信息", -1)
			return
		}
		// 统计单、多个商品的总金额，必须是主订单号
		db.Model(&models.MaOrder{}).
			Where("out_trade_no = ?", orderInfo.OutTradeNo).
			Select("*, sum(payment_amount) as total_payment_amount").
			Take(&orderInfo)
	}
	orderInfo.ModifyTime = time.Now()
	if orderInfo.PaymentID == 0 {
		return
	}
	logx.Info(ctx, "Refund", logx.Any("orderInfo.PaymentID", fmt.Sprint(orderInfo.PaymentID)))

	if orderInfo.PaymentID == 5 { // 兑换码订单
		// 清空兑换码信息
		clearCode := db.Model(&models.MaRedemptionCode{}).
			Where("out_trade_no = ?", outTradeNo).
			Updates(map[string]interface{}{
				"exchange_value":   0,
				"sales_id":         "",
				"robot_name":       "",
				"usage_time":       0,
				"new_usage_time":   0,
				"out_trade_no":     "",
				"class_id":         "",
				"goods_id":         "",
				"redemption_state": 1,
			}).RowsAffected
		if clearCode > 0 {
			orderInfo.Remarks = remarks + "_兑换码已恢复"
			orderInfo.OrderStatus = 7
		} else {
			coupon.CouponCode{}.Refund(ctx, outTradeNo)
			orderInfo.Remarks = remarks + "_兑换码已恢复"
			orderInfo.OrderStatus = 7
		}
	} else {
		// 退款统一入口
		refundCode, refundErr := or.RefundOrder(
			ctx, db,
			orderInfo.SalesID,
			outTradeNo,
			orderInfo,
			orderInfo.PaymentAmount, // 为了安全，需要使用订单查询出来的退款金额.
			reason, remarks,
			userID, // 退款的用户ID
		)
		if refundErr != nil {
			err = refundErr
		}

		// 根据退款状态执行告警通知
		switch refundCode {
		case 0:
			orderInfo.Remarks = remarks + "_退款失败"
			orderInfo.OrderStatus = 5
		case 1:
			orderInfo.Remarks = remarks + "_退款成功"
			orderInfo.OrderStatus = 6
			// 退款成功 -> 推送消息
			alarmMsg := map[string]interface{}{
				"alarm_type": 1001,
				"robot_id":   orderInfo.RobotName,
				"battery":    "",
				"content":    remarks,
				"created_at": time.Now().Unix(),
			}
			jsonString, _ := json.Marshal(alarmMsg)
			redis.NewDB().LPush(
				ctx,
				define.RedisAlarmNotifyList,
				string(jsonString),
			)
		case 2:
			orderInfo.Remarks = remarks + "_退款，保存失败"
			orderInfo.OrderStatus = 6
		}
	}

	// 处理Order订单状态 --- 如果是单条，则正常 。如果是多条，需要对子订单进行处理
	db.Model(&models.MaOrder{}).Where("out_trade_no = ?", outTradeNo).Updates(&orderInfo)
	db.Model(&models.MaOrder{}).Where("child_out_trade_no = ?", outTradeNo).Updates(&orderInfo)
	// 更新机器运营日报
	service.RobotDailyReport{}.UpdateOrder(ctx, db, orderInfo.RobotName, carbon.Now().ToDateString())
	// 更新商品运营日报
	detail, _ := dao.Goods{}.Detail(ctx, dal.Q, orderInfo.GoodsID)
	if detail != nil {
		service.GoodsDailyReport{}.UpdateOrderRefund(ctx, db, detail.GoodsID, detail.GoodsName1, carbon.Now().ToDateString())
	}
	return
}

// 执行退款 -- 统一入口
// outTradeNo 订单号【主订单号或子订单号】，用于区分是整单退还是子单退，手动退款是子订单号 【重点处理积分】
// OrderInfo 订单信息 。里面包含一个总金额，一个订单金额。
// RefundFee 退款金额 。这个是计算好的
// reason 退款原因
// remarks 退款备注
// refundUserID 退款人用户ID(仅手动退款传输)

// refundCode 0 退款失败 1 退款成功 2 退款成功保存失败
func (or OrderRefund) RefundOrder(ctx context.Context, db *gorm.DB, salesID string, outTradeNo string, OrderInfo schema.MyOrderInfo,
	RefundFee float64, reason, remarks, refundUserID string,
) (
	refundCode int, err error,
) {

	logx.Info(ctx, "RefundOrder", logx.Any("outTradeNo", outTradeNo))
	var RobotInfo models.MaRobot
	db.Model(&models.MaRobot{}).
		Where("sales_id = ? and deleted = 0", salesID).
		Take(&RobotInfo)
	if OrderInfo.PaymentID == 0 { // -- 前面已经判断，一般不会到这里
		return 0, nil
	}
	if OrderInfo.OrderStatus == 6 { // 已经退款【6】再接受到close_order时，直接退款成功
		return 1, nil
	}
	// 赠送订单不需要退款
	if OrderInfo.PaymentID == 7 {
		return 1, nil
	}

	// 获取机器配置的支付方式
	PaymentTypeMap := service.RobotPayment{}.GetRobotPayments(context.Background(), db, OrderInfo.SalesID, int(OrderInfo.PaymentID))

	if len(PaymentTypeMap) == 0 {
		// 获取商户默认支付配置
		err = errorx.New("没有设置支付方式", -1)
		return 0, nil
	}

	logx.Info(ctx, "RefundOrder", logx.Any("OrderInfo.PaymentID", fmt.Sprint(OrderInfo.PaymentID)))
	// 2 - 已支付 4 - 出货成功 5 - 出货失败
	// 生成退款单号
	orderRefundNo, _ := helper.UUID{}.String()
	// 1  -- 微信
	if OrderInfo.PaymentID == 1 {
		if _, ok := PaymentTypeMap["1"]; ok {
			WechatPayConfig, _ := dao.Payment{}.GetWechatPay(context.Background(), dal.Q, RobotInfo.MerchantID, PaymentTypeMap["1"])
			if len(WechatPayConfig) == 0 {
				err = errorx.New("微信没有配置具体的支付参数", -1)
				return 0, err
			}
			err = pay.WechatPay{}.ConfigInit(WechatPayConfig[0].WeChatAppID, WechatPayConfig[0].WeChatMchID,
				WechatPayConfig[0].WeChatAppKey, WechatPayConfig[0].CertFile)
			if err != nil {
				return 0, err
			}
			// 处理浮点数精度问题 -- 总额使用total_payment_amount字段
			myPaymentAmount := decimal.NewFromFloat(OrderInfo.TotalPaymentAmount).Mul(decimal.NewFromInt(100)).IntPart()
			myRefundFee := decimal.NewFromFloat(RefundFee).Mul(decimal.NewFromInt(100)).IntPart()
			// 请求 --- 执行退款(一个是总的订单金额，一个是需要退款的金额)
			wxpayRsp, wxpayErr := pay.WechatPay{}.Refund(OrderInfo.EndOutTradeNo, myPaymentAmount, myRefundFee) // 分
			if wxpayErr != nil || wxpayRsp.ResultCode != "SUCCESS" {
				return 0, wxpayErr
			}

			// 最后 -- 执行写入退款订单
			wxpayRspJson, _ := json.Marshal(wxpayRsp)
			refundType := OrderRefund{}.CreateRefundOrder(
				db,
				OrderInfo.MerchantID,
				OrderInfo.RobotName,
				OrderInfo.SalesID,
				OrderInfo.TotalPaymentAmount, // 总的金额
				RefundFee,                    // 退款金额
				OrderInfo.EndOutTradeNo,      // 确认订单号
				orderRefundNo,                // 退款订单号
				"",
				string(wxpayRspJson),
				OrderInfo.PaymentID,
				reason,
				remarks,
				refundUserID,
			)
			if refundType == 1 {
				return 1, nil
			} else {
				return 2, nil
			}
		}
	}
	// 2 -- 支付宝
	if OrderInfo.PaymentID == 2 {
		if _, ok := PaymentTypeMap["2"]; ok {
			AliPayConfig, _ := dao.Payment{}.GetAliPay(context.Background(), dal.Q, RobotInfo.MerchantID, PaymentTypeMap["2"])
			if len(AliPayConfig) == 0 {
				err = errorx.New("支付宝没有配置具体的支付参数", -1)
				return 0, err
			}
			err1 := pay.Alipay{}.ConfigInit(AliPayConfig[0].AliPayAppID, AliPayConfig[0].AliPayPrivateKey)
			if err1 != nil {
				err = errorx.New("支付宝配置错误", -1)
				return 0, err1
			}

			// 执行退款
			aliPayRsp, aliPayErr := pay.Alipay{}.AliPayRefund(
				OrderInfo.EndOutTradeNo,
				RefundFee, // OrderInfo.PaymentAmount, // 支付宝退款，只传一个退款金额就行
				// 0.2, // OrderInfo.PaymentAmount, // 支付宝退款，只传一个退款金额就行
				"",
				orderRefundNo, // 退款单号
			)
			if aliPayErr != nil || aliPayRsp.Response == nil || aliPayRsp.Response.Code != "10000" {
				return 0, nil
			}

			// 最后 -- 执行写入退款订单
			alipayRspJson, _ := json.Marshal(aliPayRsp)
			refundType := OrderRefund{}.CreateRefundOrder(
				db,
				OrderInfo.MerchantID,
				OrderInfo.RobotName,
				OrderInfo.SalesID,
				OrderInfo.TotalPaymentAmount, // 总的金额
				RefundFee,                    // 退款金额
				OrderInfo.EndOutTradeNo,      // 确认订单号
				orderRefundNo,                // 退款订单号
				string(alipayRspJson),
				"",
				OrderInfo.PaymentID,
				reason,
				remarks,
				refundUserID,
			)
			if refundType == 1 {
				return 1, nil
			} else {
				return 2, nil
			}
		}
	}
	// 4 -- 支付宝人脸
	if OrderInfo.PaymentID == 4 {
		if _, ok := PaymentTypeMap["4"]; ok {
			AliPayConfig, _ := dao.Payment{}.GetAliPay(context.Background(), dal.Q, RobotInfo.MerchantID, PaymentTypeMap["4"])
			if len(AliPayConfig) == 0 {
				err = errorx.New("支付宝没有配置具体的支付参数", -1)
				return 0, nil
			}
			err1 := pay.Alipay{}.ConfigInit(AliPayConfig[0].AliPayAppID, AliPayConfig[0].AliPayPrivateKey)
			if err1 != nil {
				err = errorx.New("支付宝配置错误", -1)
				return 0, nil
			}

			// 执行退款
			aliPayRsp, aliPayErr := pay.Alipay{}.AliPayRefund(
				OrderInfo.EndOutTradeNo,
				RefundFee, // // OrderInfo.PaymentAmount, // 支付宝退款，只传一个退款金额就行
				// OrderInfo.PaymentAmount, //
				"",
				orderRefundNo, // 退款单号
			)
			logx.Info(context.Background(), "支付宝退款:", logx.Any("订单号", OrderInfo.EndOutTradeNo), logx.Any("返回结果", aliPayRsp), logx.Any("返回错误", aliPayErr))
			if aliPayErr != nil || aliPayRsp.Response == nil || aliPayRsp.Response.Code != "10000" {
				return 0, nil
			}
			// 支付宝退款-生成退款订单
			alipayRspJson, _ := json.Marshal(aliPayRsp)
			refundType := OrderRefund{}.CreateRefundOrder(
				db,
				OrderInfo.MerchantID,
				OrderInfo.RobotName,
				OrderInfo.SalesID,
				OrderInfo.TotalPaymentAmount, // 总的金额
				RefundFee,                    // 退款金额
				OrderInfo.EndOutTradeNo,      // 确认订单号
				orderRefundNo,                // 退款订单号
				string(alipayRspJson),
				"",
				OrderInfo.PaymentID,
				reason,
				remarks,
				refundUserID,
			)
			if refundType == 1 {
				return 1, nil
			} else {
				return 2, nil
			}
		}
	}
	// 6 -- 大兴支付退款
	if OrderInfo.PaymentID == 6 {
		if _, ok := PaymentTypeMap["6"]; ok {
			DaxingConfig, _ := dao.Payment{}.GetDaxingPay(context.Background(), dal.Q, RobotInfo.MerchantID, PaymentTypeMap["6"])
			if len(DaxingConfig) == 0 {
				err = errorx.New("没有配置支付参数", -1)
				return 0, nil
			}
			var OrderGoodsDetail []schema.OrderGoodsDetailOld
			json.Unmarshal([]byte(OrderInfo.CountData), &OrderGoodsDetail)

			var GoodsInfo models.MaGoodsInfo
			db.Model(&models.MaGoodsInfo{}).
				Where("goods_id = ?", OrderGoodsDetail[0].GoodsID).
				Take(&GoodsInfo)

			pay.DaxingPay{}.DaxingInit(DaxingConfig[0].DxAppID, DaxingConfig[0].DxSellerID, DaxingConfig[0].DxMerchantID,
				DaxingConfig[0].DxShopID, DaxingConfig[0].DxShopID, DaxingConfig[0].DxAppKey)
			// 大兴退款
			var PayType string
			if strings.HasSuffix(OrderInfo.OutTradeNo, "W") {
				PayType = "WX"
			} else if strings.HasSuffix(OrderInfo.OutTradeNo, "A") {
				PayType = "ALI_20"
			}
			daxingPayRsp, daxingPayErr := pay.DaxingPay{}.Refund(context.Background(), OrderInfo.EndOutTradeNo, PayType, OrderInfo.PaymentAmount)
			if daxingPayErr != nil || daxingPayRsp.Header.ErrorCode != "0" {
				return 0, nil
			}
			// 向大兴发送销量
			alipayRspJson, _ := json.Marshal(daxingPayRsp)
			refundType := OrderRefund{}.CreateRefundOrder(db,
				OrderInfo.MerchantID,
				OrderInfo.RobotName,
				OrderInfo.SalesID,
				OrderInfo.PaymentAmount,
				RefundFee,
				OrderInfo.EndOutTradeNo,
				orderRefundNo,
				string(alipayRspJson),
				"",
				OrderInfo.PaymentID,
				reason,
				remarks,
				refundUserID,
			)
			if refundType == 0 {
				return 2, nil // 退款失败
			} else if refundType == 1 {
				pay.DaxingPay{}.UpSalesRefund(context.Background(), OrderInfo.EndOutTradeNo, -1, OrderInfo.PaymentAmount, GoodsInfo.GoodsCode, PayType)
				return 2, nil // 退款
			} else if refundType == 2 {
				return 1, nil // 退款，保存失败
			}
		}
	}

	// 7 -- 赠送订单
	if OrderInfo.PaymentID == 7 {
		return 1, nil
	}

	// 8 -- stripe支付
	if OrderInfo.PaymentID == 8 {
		if _, ok := PaymentTypeMap["8"]; ok {
			StripeConfig, _ := dao.Payment{}.GetStripePay(context.Background(), dal.Q, RobotInfo.MerchantID, PaymentTypeMap["8"])
			if len(StripeConfig) == 0 {
				err = errorx.New("没有配置支付参数", -1)
				return 0, nil
			}
			var OrderGoodsDetail []schema.OrderGoodsDetailOld
			json.Unmarshal([]byte(OrderInfo.CountData), &OrderGoodsDetail)

			var GoodsInfo models.MaGoodsInfo
			db.Model(&models.MaGoodsInfo{}).
				Where("goods_id = ?", OrderGoodsDetail[0].GoodsID).
				Take(&GoodsInfo)

			stripe.Key = StripeConfig[0].StripePrivKey
			params := &stripe.RefundParams{PaymentIntent: stripe.String(OrderInfo.EndOutTradeNo)}
			result, err := refund.New(params)
			if err != nil {
				if stripeErr, ok := err.(*stripe.Error); ok {
					switch stripeErr.Type {
					case stripe.ErrorType(stripe.ErrorCodeChargeAlreadyRefunded):
						logx.Error(context.Background(), "charge_already_refunded")
					}
				}
				// err.Code: "charge_already_refunded" //已退款
				logx.Info(context.Background(), "stripe refund", logx.Any("err", err.Error()))
				return 0, nil
			}
			if result.Status == "succeeded" {
				// 退款id : result.ID  : re_3NQ5JV2eZvKYlo2C17Kmgpng
				alipayRspJson, _ := json.Marshal(result)
				refundType := OrderRefund{}.CreateRefundOrder(
					db,
					OrderInfo.MerchantID,
					OrderInfo.RobotName,
					OrderInfo.SalesID,
					OrderInfo.PaymentAmount,
					RefundFee,
					OrderInfo.EndOutTradeNo,
					orderRefundNo,
					string(alipayRspJson),
					"",
					OrderInfo.PaymentID,
					reason,
					remarks,
					refundUserID,
				)
				if refundType == 1 {
					return 1, nil
				} else {
					return 2, nil
				}
			}
		}
	}
	// 9 -- 积分系统
	if OrderInfo.PaymentID == 9 {

		if pointsID, ok := PaymentTypeMap["9"]; ok {
			logx.Info(ctx, "RefundOrder", logx.Any("pointsID", fmt.Sprint(pointsID)))
			if pointsID == 1 || pointsID == 3 || pointsID == 4 || pointsID == 5 {

				refundCode = 1
				// 微信退款
				func() {

					logx.Info(ctx, "RefundOrder", logx.Any("OrderInfo.ActualAmount", fmt.Sprint(OrderInfo.ActualAmount)))
					if OrderInfo.ActualAmount > 0 { // 实付金额 > 0
						err = pay.WechatPay{}.V3ConfigInit("", "", "")
						if err != nil {
							refundCode = 0
							return
						}
						// 处理浮点数精度问题
						myPaymentAmount := decimal.NewFromFloat(OrderInfo.ActualAmount).Mul(decimal.NewFromInt(100)).IntPart()
						myRefundFee := decimal.NewFromFloat(OrderInfo.ActualAmount).Mul(decimal.NewFromInt(100)).IntPart()
						// 执行退款
						wxpayRsp, wxpayErr := pay.WechatPay{}.V3Refund(ctx, OrderInfo.EndOutTradeNo, orderRefundNo, myPaymentAmount, myRefundFee) // 分
						// SUCCESS：退款成功 CLOSED：退款关闭 PROCESSING：退款处理中 ABNORMAL：退款异常
						logx.Info(ctx, "积分 -- 微信退款", logx.Any("out_refund_no", OrderInfo.EndOutTradeNo),
							logx.Any("rsp", wxpayRsp), logx.Any("err", wxpayErr))
						if wxpayErr != nil {
							refundCode = 0
							return
						}

						// 最后 -- 执行写入退款订单
						wxpayRspJson, _ := json.Marshal(wxpayRsp)
						refundType := OrderRefund{}.CreateRefundOrder(
							db,
							OrderInfo.MerchantID,
							OrderInfo.RobotName,
							OrderInfo.SalesID,
							OrderInfo.ActualAmount,  // 订单总金额
							OrderInfo.ActualAmount,  // 退款金额
							OrderInfo.EndOutTradeNo, // 确认订单号
							orderRefundNo,           // 退款订单号
							"",
							string(wxpayRspJson),
							OrderInfo.PaymentID,
							reason,
							remarks,
							refundUserID,
						)
						if refundType == 1 {
							refundCode = 1
							return
						} else {
							refundCode = 2
							return
						}
					}
				}()
				// 积分冲正
				func() {
					OrderPointsInfo, _ := dao.OrderPoints{}.Detail(ctx, db, OrderInfo.OutTradeNo, 1)
					if OrderPointsInfo != nil && OrderPointsInfo.OutTradeNo == OrderInfo.OutTradeNo {
						// 总订单数
						var orderCount int64
						db.Model(&models.MaOrder{}).
							Where("out_trade_no = ?", OrderInfo.OutTradeNo).
							Count(&orderCount)
						// 退款订单数
						var refundOrderCount int64
						db.Model(&models.MaOrder{}).
							Where("out_trade_no = ?", OrderInfo.OutTradeNo).
							Where("order_status = 6"). // 退款
							Count(&refundOrderCount)

						// 单一订单，回正记录必须为0
						var reverseCount int64
						db.Model(&models.MaOrderPoints{}).
							Where("out_trade_no = ?", OrderInfo.OutTradeNo).
							Where("type = 2"). // 回正
							Count(&reverseCount)

						if refundOrderCount < orderCount && reverseCount == 0 {

							var refundPoints float64
							// 整单退
							// 如果传主订单号 || 订单总数 == 1
							if outTradeNo == OrderInfo.OutTradeNo || orderCount == 1 {
								refundPoints = -OrderPointsInfo.Points
							} else {
								// 分单退
								points := common.AvgDivide(-OrderPointsInfo.Points, int(orderCount), 0)
								if refundOrderCount == orderCount-1 { // 最后一个订单退款
									refundPoints = points[orderCount-1]
								} else {
									refundPoints = points[0]
								}
							}
							logx.Error(ctx, "积分路过记录，临时测试5",
								logx.Any("out_trade_no", outTradeNo),
								logx.Any("error", "error积分临时测试"),
							)
							RobotLocationInfo, _ := service.OrderPoints{}.GetRobotLocationInfo(ctx, db, OrderPointsInfo.SalesID)
							tradeErr := points.NewPoints(OrderPointsInfo.PointsID).PointsReverse(
								ctx,
								db,
								OrderPointsInfo.SalesID,        // 1. 机器识别码
								OrderPointsInfo.OpenID,         // 2. OpenID
								orderRefundNo,                  // 3. 退款单号
								OrderPointsInfo.OutTradeNo,     // 4. 订单号
								refundPoints,                   // 5. 需要退款的金额（正数）
								RobotLocationInfo.PointsMallId, // 6. 积分对接的商场ID
							)
							logx.Error(ctx, "积分路过记录，临时测试6",
								logx.Any("out_trade_no", outTradeNo),
								logx.Any("tradeErr", tradeErr),
								logx.Any("refundPoints", refundPoints),
							)
							if tradeErr != nil {
								refundCode = 0
								err = tradeErr
								return
							}
							// 订单积分冲正记录
							dao.OrderPoints{}.Create(ctx, db, OrderPointsInfo.SalesID, OrderPointsInfo.OutTradeNo, OrderPointsInfo.OpenID, 2, OrderPointsInfo.PointsID, refundPoints)
						}
					}
				}()
			} else if pointsID == 2 { // 永旺退款
				var paycode string // todo
				yongwangErr := points.YongWangPoints{}.OrderCancel(ctx, OrderInfo.OutTradeNo, paycode)
				if yongwangErr != nil {
					refundCode = 0
					return
				}
				// 积分记录冲正
				OrderPointsInfo, _ := dao.OrderPoints{}.Detail(ctx, db, OrderInfo.OutTradeNo, 1)
				if OrderPointsInfo != nil && OrderPointsInfo.OutTradeNo == OrderInfo.OutTradeNo {
					// 订单积分冲正记录
					dao.OrderPoints{}.Create(ctx, db, OrderPointsInfo.SalesID, OrderPointsInfo.OutTradeNo, OrderPointsInfo.OpenID, 2, OrderPointsInfo.PointsID, -OrderPointsInfo.Points)
				}
			}
			return refundCode, nil
		}
	}
	// 10 -- stripe_ex支付
	if OrderInfo.PaymentID == 10 {
		if _, ok := PaymentTypeMap["10"]; ok {
			pkg.StripeEx{}.Refund(ctx, OrderInfo.EndOutTradeNo, reason)
			// 查询订单状态 等待退款异步回调
			rsp, err := pkg.StripeEx{}.GetPayment(ctx, OrderInfo.EndOutTradeNo)
			if err != nil || rsp.Status != "refunded" {
				return 0, nil
			} else {
				return 1, nil
			}
		}
	}

	// 12  -- 小天才
	if OrderInfo.PaymentID == 12 {
		if _, ok := PaymentTypeMap["12"]; ok {
			WechatPayConfig, _ := dao.Payment{}.GetXiaotiancaiPay(context.Background(), dal.Q, RobotInfo.MerchantID, PaymentTypeMap["12"])
			if len(WechatPayConfig) == 0 {
				err = errorx.New("微信没有配置具体的支付参数", -1)
				return 0, nil
			}
			err = pay.WechatPay{}.ConfigInit(WechatPayConfig[0].WeChatAppID, WechatPayConfig[0].WeChatMchID,
				WechatPayConfig[0].WeChatAppKey, WechatPayConfig[0].CertFile)
			if err != nil {
				return 0, nil
			}
			// 处理浮点数精度问题 -- 总额使用total_payment_amount字段
			myPaymentAmount := decimal.NewFromFloat(OrderInfo.TotalPaymentAmount).Mul(decimal.NewFromInt(100)).IntPart()
			myRefundFee := decimal.NewFromFloat(RefundFee).Mul(decimal.NewFromInt(100)).IntPart()
			// myPaymentAmount := int64(38)
			// myRefundFee := int64(38)
			// var myRefundFee int64 = 38
			// 请求 --- 执行退款(一个是总的订单金额，一个是需要退款的金额)
			wxpayRsp, wxpayErr := pay.WechatPay{}.Refund(OrderInfo.EndOutTradeNo, myPaymentAmount, myRefundFee) // 分
			if wxpayErr != nil || wxpayRsp.ResultCode != "SUCCESS" {
				return 0, nil
			}

			// 最后 -- 执行写入退款订单
			wxpayRspJson, _ := json.Marshal(wxpayRsp)
			refundType := OrderRefund{}.CreateRefundOrder(
				db,
				OrderInfo.MerchantID,
				OrderInfo.RobotName,
				OrderInfo.SalesID,
				OrderInfo.TotalPaymentAmount, // 总的金额
				RefundFee,                    // 退款金额
				OrderInfo.EndOutTradeNo,      // 确认订单号
				orderRefundNo,                // 退款订单号
				"",
				string(wxpayRspJson),
				OrderInfo.PaymentID,
				reason,
				remarks,
				refundUserID,
			)
			if refundType == 1 {
				return 1, nil
			} else {
				return 2, nil
			}
		}
	}

	// 16 -- 小程序
	if OrderInfo.PaymentID == 16 {
		err = pay.WechatPay{}.V3ConfigInit("", "", "")
		if err != nil {
			refundCode = 0
			return
		}
		// 处理浮点数精度问题
		myPaymentAmount := decimal.NewFromFloat(OrderInfo.ActualAmount).Mul(decimal.NewFromInt(100)).IntPart()
		myRefundFee := decimal.NewFromFloat(OrderInfo.ActualAmount).Mul(decimal.NewFromInt(100)).IntPart()
		// 执行退款
		wxpayRsp, wxpayErr := pay.WechatPay{}.V3Refund(ctx, OrderInfo.EndOutTradeNo, orderRefundNo, myPaymentAmount, myRefundFee) // 分
		// SUCCESS：退款成功 CLOSED：退款关闭 PROCESSING：退款处理中 ABNORMAL：退款异常
		logx.Info(ctx, "小程序微信退款", logx.Any("out_refund_no", OrderInfo.EndOutTradeNo),
			logx.Any("rsp", wxpayRsp), logx.Any("err", wxpayErr))
		if wxpayErr != nil {
			refundCode = 0
			return
		}

		OrderPointsInfo, _ := dao.OrderPoints{}.Detail(ctx, db, OrderInfo.OutTradeNo, 1)
		refundPoints := -OrderPointsInfo.Points
		RobotLocationInfo, _ := service.OrderPoints{}.GetRobotLocationInfo(ctx, db, OrderPointsInfo.SalesID)
		var tradeErr error
		if refundPoints != 0 {
			tradeErr = points.NewPoints(OrderPointsInfo.PointsID).PointsReverse(
				ctx,
				db,
				OrderPointsInfo.SalesID,        // 1. 机器识别码
				OrderPointsInfo.OpenID,         // 2. OpenID
				orderRefundNo,                  // 3. 退款单号
				OrderPointsInfo.OutTradeNo,     // 4. 订单号
				refundPoints,                   // 5. 需要退款的金额（正数）
				RobotLocationInfo.PointsMallId, // 6. 积分对接的商场ID
			)
		}
		logx.Info(ctx, "RefundOrder", logx.Any("OrderPointsInfo.OutTradeNo", OrderPointsInfo.OutTradeNo),
			logx.Any("refundPoints", refundPoints),
			logx.Any("tradeErr", tradeErr),
			logx.Any("RobotLocationInfo.PointsMallId", RobotLocationInfo.PointsMallId))

		// 最后 -- 执行写入退款订单
		wxpayRspJson, _ := json.Marshal(wxpayRsp)
		refundType := OrderRefund{}.CreateRefundOrder(
			db, OrderInfo.MerchantID, OrderInfo.RobotName, OrderInfo.SalesID, OrderInfo.ActualAmount,
			OrderInfo.ActualAmount, OrderInfo.EndOutTradeNo, orderRefundNo,
			"", string(wxpayRspJson), OrderInfo.PaymentID, reason, remarks, refundUserID,
		)
		if refundType == 1 {
			refundCode = 1
			return
		} else {
			refundCode = 2
			return
		}
	}

	return 0, nil
}
